﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace GameStateManagement
{
    public class Target : DrawableObject //Microsoft.Xna.Framework.DrawableGameComponent
    {

        public float fUpVel, fLeftVel;
        protected Utils.Timer timers;

        public int numHits;
        public Boolean death, revive;

        public Target(Game game)
            : base(game)
        {
            this.game = (GameStateManagementGame)game;
            timers = new Utils.Timer();
            worldTransformMatrix = Matrix.Identity;
            vWorldPosition = new Vector3(0.0f, 0.0f, 0.0f);
            fScale = 0.3f;
            qRotation = Quaternion.Identity;
            hasChanged = false;

            fUpVel = 3.0f;
            fLeftVel = 3.0f;

            followCam = true;
            numHits = 20;
            death = false;
            revive = false;
        }

        public void updateRotation()
        {
            float fRadius = this.Position.Length();

            float fyAngle = (float)Math.Acos(this.Position.Y / fRadius);
            float fzAngle = (float)Math.Asin(this.Position.X / Math.Sqrt(Math.Pow(this.Position.X, 2) + Math.Pow(this.Position.Z, 2)));
            if (this.Position.Z < 0)
            {
                fzAngle = (float)Math.PI - fzAngle;
            }


            Quaternion siderot = Quaternion.CreateFromAxisAngle(Vector3.UnitY, fzAngle);
            Quaternion uprot = Quaternion.CreateFromAxisAngle(-Vector3.UnitX, (float)(Math.PI / 2.0) - fyAngle);

            this.Rotation = siderot * uprot;

            updateWorldTransformMatrix();

        }

        public override void Initialize()
        {
            updateRotation();
            base.Initialize();

        }

        public float Scale
        {
            get { return fScale; }
            set
            {
                fScale = value;
                hasChanged = true;
            }
        }

        public Vector3 Position
        {
            get { return vWorldPosition; }
            set
            {
                vWorldPosition = value;
                hasChanged = true;
            }
        }

        public Quaternion Rotation
        {
            get { return qRotation; }
            set { qRotation = value; }
        }

        public void switchCam()
        {
            followCam = !followCam;
        }

        /*public void updateWorldTransformMatrix()
        {
            hasChanged = false;

            Matrix scaleMatrix = Matrix.CreateScale(fScale);
            Matrix rotationMatrix = Matrix.CreateFromQuaternion(qRotation);
            Matrix translationMatrix = Matrix.CreateTranslation(vWorldPosition);

            worldTransformMatrix = scaleMatrix;
            worldTransformMatrix *= rotationMatrix;
            worldTransformMatrix *= translationMatrix;

            WorldBounds.Center = vWorldPosition;
            WorldBounds.Radius = ModelBounds.Radius * fScale;
        }*/

        public override void Update(GameTime gameTime)
        {
            if (!death)
            {
                Vector3 oldpos = this.Position;

                float fRadius = this.Position.Length();

                float dTime = ((float)gameTime.ElapsedGameTime.Ticks / System.TimeSpan.TicksPerMillisecond / 1000.0f);

                Random random = new Random();
                if (random.Next(1000) < 2)
                {
                    fLeftVel = -fLeftVel;
                    fUpVel = -fUpVel;
                }

                Vector3 left = this.worldTransformMatrix.Left;
                Vector3 newPos = this.Position + (this.worldTransformMatrix.Up * fUpVel * (fRadius / 350.0f));
                newPos.Normalize();
                newPos *= fRadius;
                this.Position = newPos;

                this.updateRotation();
                this.worldTransformMatrix.Left = left;
                this.worldTransformMatrix.Up = Vector3.Cross(this.worldTransformMatrix.Forward, left) / fScale;


                Vector3 up = this.worldTransformMatrix.Up;
                newPos = this.Position + (this.worldTransformMatrix.Left * fLeftVel * (fRadius / 350.0f));
                newPos.Normalize();
                newPos *= fRadius;
                this.Position = newPos;

                this.updateRotation();

                this.worldTransformMatrix.Up = up;
                this.worldTransformMatrix.Left = -Vector3.Cross(this.worldTransformMatrix.Forward, this.worldTransformMatrix.Up) / fScale;
            }
            else
            {
                if (revive)
                {
                    Vector3 pos = this.Position;
                    pos *= 1.05f;
                    this.Position = pos;
                    
                }
                else if (this.Position.Length() >= 100.0f)
                {
                    Vector3 pos = this.Position;
                    pos.Normalize();
                    pos *= this.Position.Length() - 0.5f;
                    this.Position = pos;
                }
                else
                {
                    death = false;
                    
                    Random random = new Random();
                    float fzAngle, fyAngle;
                    fzAngle = (float)(random.NextDouble() * Math.PI);
                    fyAngle = (float)(random.NextDouble() * Math.PI);

                    float x = 40.0f * (float)(Math.Sin(fyAngle) * Math.Sin(fzAngle));
                    float y = 40.0f * (float)Math.Cos(fyAngle);
                    float z = 40.0f * (float)(Math.Sin(fyAngle) * Math.Cos(fzAngle));

                    Vector3 pos = new Vector3(x, y, z);

                    this.Position = pos;
                    this.updateRotation();
                    revive = true;

                }

            }
            
            timers.Update(gameTime);
            base.Update(gameTime);
        }

        public void hit()
        {
            

            Random random = new Random();
            if (random.Next(10) == 9)
            {
                fLeftVel = 3.0f * (float)random.NextDouble() + 2.0f;
                fUpVel = 3.0f * (float)random.NextDouble() + 2.0f;
                if (random.NextDouble() > 0.5f)
                {
                    fLeftVel = -fLeftVel;
                }
                if (random.NextDouble() > 0.5f)
                {
                    fUpVel = -fUpVel;
                }

            }

        }

        public void deathStart()
        {
            death = true;

            

        }

        public float getRadius()
        {
            return WorldBounds.Radius * 11.8f;
        }

        protected override void LoadContent()
        {
            contentManager = new ContentManager(Game.Services, "Content");
            actorModel = contentManager.Load<Model>("bubble");
            actorBones = new Matrix[actorModel.Bones.Count];
            celShader = contentManager.Load<Effect>("CelShader");
            texture = contentManager.Load<Texture2D>("bubblegum");
            celShader.Parameters["Texture"].SetValue(texture);
            celShader.Parameters["textureEnabled"].SetValue(true);
           /* float[] temp = new float[2] { 3.0f, 0.01f };
            celShader.Parameters["toonThresholds"].SetValue(temp);
            temp = new float[3] { 1.3f, 0.6f, 0.4f };
            celShader.Parameters["toonBrightnessLevels"].SetValue(temp);*/
            
            changeEffectUsedByModel(actorModel, celShader);


            base.LoadContent();

            foreach (ModelMesh mesh in actorModel.Meshes)
            {
                ModelBounds = BoundingSphere.CreateMerged(ModelBounds,
                mesh.BoundingSphere);
            }

        }

        protected override void UnloadContent()
        {
            contentManager.Unload();
            base.UnloadContent();
        }

       /* public override void Draw(GameTime gameTime)
        {
            if (hasChanged)
            {
                updateWorldTransformMatrix();
            }

            GraphicsDevice.RenderState.DepthBufferEnable = true;
            actorModel.CopyAbsoluteBoneTransformsTo(actorBones);
            foreach (ModelMesh mesh in actorModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World =
                    actorBones[mesh.ParentBone.Index] * worldTransformMatrix;
                    if (followCam)
                    {
                        effect.View = GameplayScreen.camera.View;
                        effect.Projection = GameplayScreen.camera.Projection;
                    }
                    else
                    {
                        effect.View = GameplayScreen.CameraMatrix;
                        effect.Projection = GameplayScreen.ProjectionMatrix;
                    }
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.AmbientLightColor = GameplayScreen.ambientLightColor;
                    effect.DirectionalLight0.DiffuseColor = GameplayScreen.diffuseColor;
                    effect.DirectionalLight0.Direction = GameplayScreen.diffuseDirection;
                    effect.SpecularColor = GameplayScreen.specularColor;
                    effect.SpecularPower = GameplayScreen.specularPower;

                }
                mesh.Draw();
            }
            base.Draw(gameTime);
        }*/


    }
}
